/*
    Speedbump aka Project Kimbula
    Copyright (C) 2010  Ping Shin Ching

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see http://www.gnu.org/licenses.

	Ping Shin Ching
	righteous.ninja@gmail.com OR ping_sc@hotmail.com
	More information at http://www.tidytutorials.com/p/speedbump.html
 */

/* 
 * Really simple doubly linked list to support the cache
 */
#include <malloc.h>
struct SimpleDoublyLinkedListItem{
	SimpleDoublyLinkedListItem* previous;
	SimpleDoublyLinkedListItem* next;
	void* payload;
};
class SimpleDoublyLinkedList{
private:
	SimpleDoublyLinkedListItem* start;
	SimpleDoublyLinkedListItem* end;

	/*internal*/
	void _add_end(SimpleDoublyLinkedListItem* i){
		i->next=0;
		if(!end){
			end=i;
			start=i;
			i->previous=0;
		}
		else{
			end->next=i;
			i->previous=end;
			end=i;
		}	
	
	}
	void _remove(SimpleDoublyLinkedListItem* i){
		if(i->previous)
			i->previous->next=i->next;
		else
			start=i->next;	
		if(i->next)
			i->next->previous=i->previous;
		else
			end=i->previous;
	}

public:
	SimpleDoublyLinkedList(){
		start=0;
		end=0;
	}
	SimpleDoublyLinkedListItem* add_end(void* payload){
		SimpleDoublyLinkedListItem * tlis = (SimpleDoublyLinkedListItem*)malloc(sizeof(SimpleDoublyLinkedListItem));
		tlis->payload=payload;
		tlis->next=0;
		_add_end(tlis);
		return tlis;
	}
	int remove(SimpleDoublyLinkedListItem* l){
		_remove(l);
		free(l);
	}
	SimpleDoublyLinkedListItem* get_last(){
		return end;
	}
	SimpleDoublyLinkedListItem* get_first(){
		return start;
	}
	void show_all(void(*f)(void*),int reverse=0){
		SimpleDoublyLinkedListItem* i;
		if(!reverse)
			for (i=start; i!=0; i=i->next)
				f(i->payload);	
		else
			for (i=end; i!=0; i=i->previous)
				f(i->payload);	
	}
	void remove_all(void(*f)(void*)=0){
		SimpleDoublyLinkedListItem* i, *t;
		i=start;
		while(i){
			if(!f)
				free(i->payload);	
			else
				f(i->payload);
			t=i;
			i=i->next;
			free(t);
		}
	}
	void move_to_end(SimpleDoublyLinkedListItem* l){
		_remove(l);
		_add_end(l);
	}
};
